package com.rs2hd.combat;

import com.rs2hd.event.Event;

import com.rs2hd.model.Bonuses;
import com.rs2hd.model.NPC;
import com.rs2hd.model.Player;
import com.rs2hd.model.World;
import com.rs2hd.model.Skills;
import com.rs2hd.util.Misc;
import com.rs2hd.content.NPCDROP;

public class PlayerCombat {
public Magic ma;

	                boolean freeze = false;
	                boolean barrage = false;
	                int freezeDelay = 0;
	public boolean usingAncient;
	private Player p = null;
public Player player;
	public int enemyIndex = 0;
	public boolean attacking = false;
	public int combatDelay = 0;
	public boolean useSpec = false;
	public int attackStyle = 1;
	public int specialAmount = 1000;
	public int restoreDelay = 25;
	public int inCombatWith = 0;
	public int combatWithTime = 0;
	public boolean attackNpc = false;
	public int enemyId;
	public PlayerCombat(Player p) {
		this.p = p;
	}
	public void refreshSpecial() {
		p.getActionSender().sendConfig(300, specialAmount);
	}
	public void tick() {
		if(combatDelay > 0) {
			combatDelay--;
		}
		if(attacking) {
			attack();
		}
		if(combatWithTime > 0) {
			combatWithTime--;
		}
		if(combatWithTime == 0) {
			inCombatWith = 0;
		}
		if (attackNpc) {
			attackNpc();
		}
		if (specialAmount < 1000) {
			if(restoreDelay > 0) {
				restoreDelay--;
			}
			if(restoreDelay == 0) {
				restoreDelay = 25;
				specialAmount += 250;
			}
			refreshSpecial();
		}
	}

	public void attack() {
		if (p == null || !attacking || p.isDead()) {
			attacking = false;
			p.following = false;
			return;
		}
		p.followIndex = enemyIndex;
		p.following = true;
		if(combatDelay > 0) {
			return;
		}
                if (attackStyle == 0) {
                      p.getSkills().addXp(3, 1000);
                      p.getSkills().addXp(0, 1400);
                }
                if (attackStyle == 1) {
                      p.getSkills().addXp(3, 1000);
                      p.getSkills().addXp(2, 1400);
                }
                if (attackStyle == 2) {
                      p.getSkills().addXp(3, 1000);
                      p.getSkills().addXp(1, 1400);
                }
                if (attackStyle == 3) {
                      p.getSkills().addXp(3, 1000);
                      p.getSkills().addXp(2, 1400);
                }
		final Player opp = World.getInstance().getPlayerList().get(enemyIndex);
		if (opp == null || opp.isDead()) {
			attacking = false;
			return;
		}
		p.turnTemporarilyTo(opp);
		if (p.SafeZone()) {
			p.getActionSender().sendMessage("You are not in a PvP area to be allowed to attack!");
			attacking = false;
			p.following = false;
			return;
		}
		if (opp.SafeZone()) {
			p.getActionSender().sendMessage("This player is not in a PvP area to be attacked!");
			attacking = false;
			p.following = false;
			return;
		}
		if (p.corp()) {
			p.getActionSender().sendMessage("You are not in a PvP area to be allowed to attack!");
			attacking = false;
			p.following = false;
			return;
		}
		if (opp.corp()) {
			p.getActionSender().sendMessage("This player is not in a PvP area to be attacked!");
			attacking = false;
			p.following = false;
			return;
		 }
		 if (p.getCombat().inCombatWith != opp.getIndex() && p.getCombat().inCombatWith != 0) {	
		  if (opp.NormalZone()) {			
			p.getActionSender().sendMessage("You are already in combat.");	
			attacking = false;
			p.following = false;
			return;
                   }
                 }
		 if (opp.getCombat().inCombatWith != p.getIndex() && opp.getCombat().inCombatWith != 0 ) {
		  if (p.NormalZone()) {				
			p.getActionSender().sendMessage("That player is already in combat.");	
			attacking = false;
			p.following = false;
			return;
                  }
                }
		inCombatWith = opp.getIndex();
		combatWithTime = 8;
		opp.getCombat().inCombatWith = p.getIndex();
		opp.getCombat().combatWithTime = 8;
		final int distance1 = Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(),opp.getLocation().getX(), opp.getLocation().getY());
		if(useSpec) {
			Player player = p;
			if (player.getEquipment().get(3) == null) {
				useSpec = false;
				return;
			}
			int id = player.getEquipment().get(3).getId();
			int req = getRequiredLevel(id);
			int meleeDamage = Misc.random(p.MaxHitSpec());
			int meleeDamage2 = Misc.random(p.MaxHitSpec());
			int r = Misc.random(p.MaxHitRange());
			int r1 = Misc.random(p.MaxHitRange());
			if(specialAmount >= req) {
				specialAmount -= req;
				refreshSpecial();
			} else {
				player.getActionSender().sendMessage("You do not have enough special amount left.");
				player.setAttacking(false);
				player.getActionSender().sendConfig(301, 0);
				refreshSpecial();
				return;
			}
			Player p2 = opp;
			opp.updateHit(p, meleeDamage);
			int specialDamage = Misc.random((int) (p.MaxHitSpec() * 1.20));
			switch (id) {
			case 4153:
				if (p.getCombat().attacking) {
					if (p.wearingGMAUL() && p.getCombat().specialAmount >= 50) {
						if (opp == null) {
							return;
						}
						p.getCombat().specialAmount -= 500;
						p.getCombat().refreshSpecial();
						p.animate(1667, 0);
						p.graphics(340, 0);
						p.getCombat().combatDelay = 7;
						int hitDamage = Misc.random(player.MaxHitSpec());
						int hitDamage2 = Misc.random(player.MaxHitSpec());
						opp.hit(hitDamage);
						opp.hit(hitDamage2);
						player.getActionSender().sendConfig(301, 0);
						player.setSpecial(false);
						return;
					} else if (p.wearingGMAUL() && p.getCombat().specialAmount <= 49) {
						p.getActionSender().sendMessage("You don't have enough special energy.");
						player.getActionSender().sendConfig(301, 0);
						player.setSpecial(false);
						return;
					}
				}
			break;
			case 13899: //Vesta's long
                               p2.animate(4177, 0);
				p.animate(10502, 0);
				if (p.Defence()) {										
				p2.hit(Misc.random(60));
			} else {
				p2.hit(meleeDamage);
                                }
                                
				break;
			case 13902: //Statius warhammer
                               p2.animate(4177, 0);
				p.graphics(1840, 0);
				p.animate(10505, 0);
				if (p.Defence()) {
				p2.hit(Misc.random(60));
                        } else {
				p2.hit(specialDamage);
                                }
				break;
			case 4151: //whip
				p2.graphics(2108, 0);
				p.animate(1658, 0);
				p2.hit(meleeDamage);
				break;
			case 15259:
				p2.hit(meleeDamage);
				p.animate(12031);
				p.graphics(2144);
				break;
				case 14484:
                                        p2.animate(4177, 0);
					p.graphics(1950, 0);
					p.animate(10961, 0);
					p2.animate(403);
					int dclaw1 = meleeDamage/2;
					int dclaw2 = meleeDamage/3;
					int dclaw3 = meleeDamage/4;
					if (p.Defence()) {										
						p2.hit(Misc.random(25));
					} else {
						p2.hit(Misc.random(25));
					}
					if (p.Defence()) {	
						p2.hit(Misc.random(35));									
					} else {
						p2.hit(Misc.random(35));
					}
					if (p.Defence()) {										
						p2.hit(Misc.random(10));
					} else {
						p2.hit(Misc.random(10));
					}
					if (p.Defence()) {										
						p2.hit(Misc.random(5));
					} else {
                                                p2.hit(Misc.random(5));
					}
                                        									
					break;

			case 861:
                                p.graphics(250, (100 << 16));
                                p2.animate(4177, 0);
				p.animate(1074, 0);
				if (p.Defence()) {
				p2.hit(Misc.random(25));
                        } else {
				p2.hit(r);
                                }
				if (p.Defence()) {
				p2.hit(Misc.random(23));
                        } else {
				p2.hit(r1);
                                }
				break;

			        case 13879:
                                p2.animate(4177, 0);
			        p.graphics(1836, 0);
			        p.animate(10501, 0);
				if (p.Defence()) {
				p2.hit(Misc.random(46));
                        } else {
				p2.hit(r);
                                }
				break;
                        case 1215:
			case 5698:
                               p2.animate(4177, 0);
				p.graphics(252, (100 << 16));
				p.animate(1062, 0);
				if (p.Defence()) {
				p2.hit(Misc.random(42));
                        } else {
				p2.hit(meleeDamage);
                                }
				if (p.Defence()) {
				p2.hit(Misc.random(35));
                        } else {
				p2.hit(meleeDamage2);
                                }
                                
				break;
			case 11730:
                               p2.animate(4177, 0);
				p.graphics(1224, 0);
				p2.graphics(1194, 0);
				p.animate(7072, 0);
				p2.hit(meleeDamage);
				p2.hit(meleeDamage2);
				break;
			case 11694:
                                p2.animate(4177, 0);
				p.graphics(1222, 0);
				p.animate(7074, 0);
				if (p.Defence()) {
				p2.hit(Misc.random(70));
                        } else {
				p2.hit(meleeDamage);
                                }
				break;
			case 11696:
                               p2.animate(4177, 0);
				p.graphics(1223, 0);
				p.animate(7073, 0);
                                p2.getSkills().drainDefence(meleeDamage/4);
                                p2.getSkills().refreshLvls(); 
				p2.hit(Misc.random((int) (p.MaxHitSpec() * 1.10)));
				break;
			case 11698:
                               p2.animate(4177, 0);
				p.graphics(1220, 0);
				p.animate(7071, 0);
				p2.hit(meleeDamage);
				break;
			case 11700:
                               p2.animate(4177, 0);
				p.graphics(1221, 0);
				p.animate(7070, 0);
				p2.hit(meleeDamage);
				break;

				case 15241:
                                p2.animate(4177, 0);
                                p.animate(12174, 0);
				p.graphics(2138, 0);
				p2.hit(Misc.random(50));
				p2.hit(Misc.random(40));
				break;
			case 1305:
				p.graphics(248, 0);
				p.animate(1058, 0);
				p2.hit(Misc.random((int) (p.MaxHitSpec() * 1.20)));
				break;
			case 4587:
				p.graphics(347, 0);
				p.animate(2081, 0);
				p2.hit(meleeDamage);
				break;
			case 3204:
				p.graphics(282, 0);
				p2.graphics(254, 0);
				p.animate(1665, 0);
				p2.hit(meleeDamage);
				p2.hit(meleeDamage2);
				break;
			case 1434:
				p.graphics(251, 0);
				p.animate(1060, 0);
				p2.hit(Misc.random((int) (p.MaxHitSpec() * 1.25)));
				break;
			case 7158:
				p.graphics(559, 0);
				p.animate(3157, 0);
				p2.hit(meleeDamage);
				break;
			} 
			player.getActionSender().sendConfig(301, 0);
			refreshSpecial();
			combatDelay = getAttackDelay();
			useSpec = false;
			return;
		        }
                
		if(usingRange()) {
			handleRange(p, opp);
			return;
		}
		final int distance = Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(),opp.getLocation().getX(), opp.getLocation().getY());
		if (!usingRange() && distance <= 1 && combatDelay == 0) {
			if (p.getEquipment().get(3) != null) {
				p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()));
			} else {
				p.animate(451);
			}
			combatDelay = getAttackDelay();
			World.getInstance().registerEvent(new Event(getDamageDelay()) {
				@Override
				public void execute() {
					if (opp.getEquipment().get(3) != null) {
						opp.animate(getBlockEmote(opp.getEquipment().get(3).getDefinition().getId())); 
					} else { 
						opp.animate(404); 
					}
					int damage = p.MaxHitMelee();
					opp.hit(damage);
					opp.updateHit(p, damage);
					if(opp.usingVeng) {
						p.hit((int)((damage / 4) * 3));
						opp.forceChat("Taste Vengeance!");
						opp.getUpdateFlags().setForceTextUpdateRequired(true);
						opp.vengDelay = 60;
						opp.vengUseDelay = 0;
						opp.usingVeng = false;
						World.getInstance().registerEvent(new Event(400) {
							@Override
							public void execute() {
								opp.getUpdateFlags().setForceTextUpdateRequired(false);
								this.stop();
							}
						});
					}
					this.stop();
				}
			});
		}
	}
	public int getDamageDelay() {
		if (p.getEquipment().get(3) == null) {
			return 140;
		}
		switch (p.getEquipment().get(3).getDefinition().getId()) {
		case 4151: return 180;
		case 11694:
		case 15241:
		case 11696:
		case 11698:
		case 11700: return 220;
		}
		return 140;
	}
	public int getAttackDelay() {
		if (p.getEquipment().get(3) != null) {
			switch(p.getEquipment().get(3).getDefinition().getId()) {
			case 863:
			case 864:
			case 865:
			case 866:
			case 867:
			case 868:
			case 869: return 2;
			case 10581: return 6;
			case 13902: return 6;
			case 4153: return 7;
			case 4734: return 3;
			case 9703: return 5;
			case 9185: return 5;
			case 4675: return 5;
			case 13867: return 5;
			case 13879: return 5;
			case 4718: return 8;
			case 11235: return 8;
			case 4755: return 5;
			case 11730: return 5;
			case 11696: 
			case 11694: 
			case 15241: 
			case 11698:
			case 11700:
			case 1307:
			case 1309: 
			case 1311: 
			case 1313: 
			case 1315:
			case 1317:
			case 1319: return 7;
			case 4151: return 4;
			default: return 4;
			}
		}
		return 4;
	}
        public void freezeDelay(final Player p, final Player opp) {
		if (freeze) {
		    if (opp.frozen == 0) {
			 opp.frozen = freezeDelay;
                            opp.graphics(369, 0);
                              opp.getWalkingQueue().reset();
		} else {
		   opp.graphics(1677, (100 << 16));
              }
           }
        }
	private void handleRange(final Player p, final Player opp) {
		p.getWalkingQueue().reset();
		if (p.getEquipment().get(3).getDefinition().getId() == 15241) {
			System.out.println("DONE");
                                p.animate(12174, 0);
				p.graphics(2138, 0);
			combatDelay = getAttackDelay();
			int damage = p.MaxHitRange();
			int damage2 = p.MaxHitRange();
                          opp.hit(Misc.random(35));
			return;
		}
                else if (p.getEquipment().get(3).getDefinition().getId() == 861) {
			System.out.println("DONE");
                                p.animate(426, 0);
                        p.graphics(24, (100 << 16));
			combatDelay = getAttackDelay();
			int damage = p.MaxHitRange();
			int damage2 = p.MaxHitRange();
                        int dam = p.MaxHitSpec();
                          if (p.Defence()) {										
				opp.hit(Misc.random(25));
			   } else {
				opp.hit(dam);
			}
			return;
		}
                else if (p.getEquipment().get(3).getDefinition().getId() == 9185) {
			System.out.println("DONE");
p.animate(4230, 0);
			combatDelay = getAttackDelay();
			int damage = p.MaxHitRange();
			int damage2 = p.MaxHitRange();
                        int dam = p.MaxHitSpec();
                          if (p.Defence()) {										
				opp.hit(Misc.random(60));
			   } else {
				opp.hit(dam);
			}
			return;
		}
                else if (p.getEquipment().get(3).getDefinition().getId() == 4675) {
			System.out.println("DONE");
                                p.animate(1979, 0);
                                p.graphics(368, 0);
                                freezeDelay(p, opp);
				freeze = true;
				freezeDelay = 20;
			combatDelay = getAttackDelay();
			int damage = p.MaxHitRange();
			int damage2 = p.MaxHitRange();
                        int dam = p.MaxHitSpec();										
				opp.hit(Misc.random(30));
			return;
		}
                else if (p.getEquipment().get(3).getDefinition().getId() == 13867) {
			System.out.println("DONE");
                                p.animate(10518, 0);
                                opp.graphics(1853, 0);
			combatDelay = getAttackDelay();
			int damage = p.MaxHitRange();
			int damage2 = p.MaxHitRange();
                        int dam = p.MaxHitSpec();										
				opp.hit(Misc.random(38));
			return;
		}
                else if (p.getEquipment().get(3).getDefinition().getId() == 13879) {
			System.out.println("DONE");
                                p.animate(806, 0);
                        p.graphics(1837, (150 << 18));
			combatDelay = getAttackDelay();
			int damage = p.MaxHitRange();
			int damage2 = p.MaxHitRange();
                        int dam = p.MaxHitSpec();
                          if (p.Defence()) {										
				opp.hit(Misc.random(44));
			   } else {
				opp.hit(dam);
			}
			return;
		}
		if (usingBow(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(DrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingDarts(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(DartDrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingKnifes(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(KnifeDrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingAxes(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(AxeDrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingJavelins(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(JavelinDrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingCrossBow(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
		}
		if (usingCrystalBow(p)) {
			p.animate(426, 0);
			p.graphics(250, (100 << 16));
			combatDelay = getAttackDelay();
		}
		World.getInstance().registerEvent(new Event(getRangeDelay()) {
			@Override
			public void execute() {
				if (opp.getEquipment().get(3) != null) {
					opp.animate(getBlockEmote(opp.getEquipment().get(3).getDefinition().getId())); 
				} else { 
					opp.animate(404); 
				}
				int damage = p.MaxHitRange();
				opp.hit(damage);
				opp.updateHit(p, damage);
				if(opp.usingVeng) {
					p.hit((int)((damage / 4) * 3));
					opp.getUpdateFlags().setForceTextUpdateRequired(true);
					opp.forceChat("Taste Vengeance!");
					opp.vengDelay = 60;
					opp.vengUseDelay = 0;
					opp.usingVeng = false;
					World.getInstance().registerEvent(new Event(400) {
						@Override
						public void execute() {
							opp.getUpdateFlags().setForceTextUpdateRequired(false);
							this.stop();
						}
					});
				}
				this.stop();
			}
		});
	}
	private int getRequiredLevel(int id) {
		switch (id) {
		case 13899:  return 250; //Vesta's long
		case 4153: return 500;
		case 13902: return 500;
		case 11694:
			return 500;
		case 15241:
			return 500;
		case 11696:
			return 1000;
		case 11698:
			return 750;
		case 10887:
			return 500;
		case 11700:
			return 550;
		case 11730:
			return 650;
		case 4151:
			return 500;
		case 1305:
			return 250;
		case 4587:
			return 700;
		case 1434:
			return 400;
		case 3204:
			return 1000;
		case 5698:
			return 250;
		case 13879:
			return 500;
		case 1215:
			return 250;
		case 861:
			return 600;
		case 14484:
                        return 500;
                 default:
                        return 0;
		}
	}
	public int BestAttackBonus() {
		Bonuses bonuses = p.getBonuses();
		if(bonuses.getBonus(0) > bonuses.getBonus(1) && bonuses.getBonus(0) > bonuses.getBonus(2)) {
			return 0;
		}
		if(bonuses.getBonus(1) > bonuses.getBonus(0) && bonuses.getBonus(1) > bonuses.getBonus(2)) {
			return 1;
		}
		if(bonuses.getBonus(2) > bonuses.getBonus(1) ||  bonuses.getBonus(2) > bonuses.getBonus(0)) {
			return 2;
		}
		return 1;
	}
	public int DefenceBonus(int BestAttackBonus) {
		if(BestAttackBonus == 0)
			return 5;
		if(BestAttackBonus == 1)
			return 6;
		if(BestAttackBonus == 2)
			return 7;
		return 5;
	}
	private int getBlockEmote(int id) {
		if (id == 10887) {
			return 5866;
		}
		if(id == 15241) {
			return 1666;
		}
		if (id == 4031) {
			return 221;
		}
		if (id == 4151) {
			return 1659;
		}
		if (id == 8850) {
			return 4177;
		}
		if (id == 4718 ||
				id == -1) {
			return 424;
		}
		if (id == 4755) {
			return 2063;
		}
		if (id == 10887) {
			return 5866;
		}
		if (id == 4153) {
			return 1666;
		}
		if (id == 11694 ||
				id == 11696 ||
				id == 11698 ||
				id == 11700 ||
				id == 1307 ||
				id == 1309 || 
				id == 1311 || 
				id == 1313 || 
				id == 1315 ||
				id == 1317 ||
				id == 1319 ||
				id == 7158) {
			return 7050;
		}
		if (id == 3204) {
			return 420;
		}
		return 404;
	}
	private int getCombatAnim(int id) {

		if (id == -1) {
			if (attackStyle != 2)
				return 422;
			else
				return 423;
		}
		if(id == 15241) {
			return 12175;
		}
		if (id == 4718) {
			if (attackStyle != 2)
				return 2067;
			else
				return 2066;
		}
		if (id == 10581) {
			return 402;
		}
		if (id == 4153) {
			return 1665;
		}
		if (id == 4734) {
			return 2075;
		}
		if (id == 9703) {
			return 412;
		}
		if (id == 3204) {
			return 440;
		}
		if (id == 11696 || id == 11694 || id == 11698 || id == 11700 ||
				id == 1307 ||
				id == 1309 || 
				id == 1311 || 
				id == 1313 || 
				id == 1315 ||
				id == 1317 ||
				id == 1319 || id == 11730) {
			return 7041;
		}
		for (int i = 1265; i < 1276; i++) {
			if (id == i) {
				return 401;
			}
		}
		if (id == 4755) {
			return 2062;
		}
		if (id == 10887) {
			return 5865;
		}
		if (id == 4151) {
			return 1658;
		}
		if (id == 5698) {
			return 402;
		}
		for (int i = 0; i <  rangeBows.length; i++)
			if (id ==  rangeBows[i] || id == 11235 || id == 9705 || id == 4212 || id == 4214)
				return 426;

		for (int i = 0; i <  Knifes.length; i++)
			if (id ==  Knifes[i])
				return 806;

		for (int i = 0; i <  Darts.length; i++)
			if (id ==  Darts[i])
				return 582;

		for (int i = 0; i <  Axes.length; i++)
			if (id ==  Axes[i])
				return 806;

		for (int i = 0; i <  CrossBows.length; i++)
			if (id ==  CrossBows[i])
				return 4230;

		for (int i = 0; i < Javelins.length; i++)
			if (id ==  Javelins[i])
				return 806;
		return 451;
	}
	public boolean usingRange() {
		return usingBow(p) || usingCrystalBow(p) || usingCrossBow(p) || usingKnifes(p) || usingDarts(p) || usingAxes(p) || usingJavelins(p);
	}
	private boolean usingBow(final Player p) {
		for (int i = 0; i < rangeBows.length; i++) {
			if(p.getEquipment().get(3) != null)
				if (p.getEquipment().get(3).getDefinition().getId() == rangeBows[i] || p.getEquipment().get(3).getDefinition().getId() == 11235 || p.getEquipment().get(3).getDefinition().getId() == 15241 || p.getEquipment().get(3).getDefinition().getId() == 13879) {
					return true;
				}
		}
		return false;
	}
	private boolean usingCrystalBow(final Player p) {
		for (int i = 0; i < CrystalBows.length; i++) {
			if(p.getEquipment().get(3) != null)
				if (p.getEquipment().get(3).getDefinition().getId() == CrystalBows[i]) {
					return true;
				}
		}
		return false;
	}
	private boolean usingCrossBow(final Player p) {
		for (int i = 0; i < CrossBows.length; i++) {
			if(p.getEquipment().get(3) != null)
				if (p.getEquipment().get(3).getDefinition().getId() == CrossBows[i]) {
					return true;
				}
		}
		return false;
	}
	private boolean usingKnifes(final Player p) {
		for (int i = 0; i < Knifes.length; i++) {
			if(p.getEquipment().get(3) != null)
				if (p.getEquipment().get(3).getDefinition().getId() == Knifes[i]) {
					return true;
				}
		}
		return false;
	}
	private boolean usingDarts(final Player p) {
		for (int i = 0; i < Darts.length; i++) {
			if(p.getEquipment().get(3) != null)
				if (p.getEquipment().get(3).getDefinition().getId() == Darts[i]) {
					return true;
				}
		}
		return false;
	}
	private boolean usingAxes(final Player p) {
		for (int i = 0; i < Axes.length; i++) {
			if(p.getEquipment().get(3) != null)
				if (p.getEquipment().get(3).getDefinition().getId() == Axes[i]) {
					return true;
				}
		}
		return false;
	}
	private boolean usingJavelins(final Player p) {
		for (int i = 0; i < Javelins.length; i++) {
			if(p.getEquipment().get(3) != null)
				if (p.getEquipment().get(3).getDefinition().getId() == Javelins[i]) {
					return true;
				}
		}
		return false;
	}

	private int DrawBack(final int ID) {
		switch(ID) {
		case 78: return 25; // Ice Arrows
		case 598: return 26; // Bronze Fire Arrow
		case 882: return 19; // Bronze Arrow
		case 883: return 19; // Bronze Arrow(p)
		case 884: return 18; // Iron Arrow
		case 885: return 18; // Iron Arrow(p)
		case 886: return 20; // Steel Arrow
		case 887: return 20; // Steel Arrow(p)
		case 888: return 21; // Mithril Arrow
		case 889: return 21; // Mithril Arrow(p)
		case 890: return 22; // Adamant Arrow
		case 891: return 22; // Adamant Arrow(p)
		case 892: return 24; // Rune Arrow
		case 893: return 24; // Rune Arrow(p)
		case 942: return 26; // Bronze Fire Arrows
		case 2532: return 26; // Iron Fire Arrows
		case 2533: return 26; // Iron Fire Arrows
		case 2534: return 26; // Steel Fire Arrows
		case 2535: return 26; // Steel Fire Arrows
		case 2536: return 26; // Mithril Fire Arrows
		case 2537: return 26; // Mithril Fire Arrows
		case 2538: return 26; // Addy Fire Arrows
		case 2539: return 26; // Addy Fire Arrows
		case 2540: return 26; // Rune Fire Arrows
		case 2541: return 26; // Rune Fire Arrows
		//case 2866:  // Ogre Arrow
		case 4150: return 1293; // Broad Arrows
		case 4160: return 1293; // Broad Arrows
		case 4172: return 1293; // Broad Arrows
		case 4173: return 1293; // Broad Arrows
		case 4174: return 1293; // Broad Arrows
		case 4175: return 1293; // Broad Arrows
		case 4773: return 19; // Bronze_brutal
		case 4778: return 18; // Iron_brutal
		case 4783: return 20; // Steel_brutal
		case 4788: return 23; // Black_brutal
		case 4793: return 21; // Mithril_brutal
		case 4798: return 22; // Adamant_brutal
		case 4803: return 24; // Rune_brutal
		case 5616: return 19; // Bronze Arrow(p+)
		case 5617: return 18; // Iron Arrow(p+)
		case 5618: return 20; // Steel Arrow(p+)
		case 5619: return 21; // Mithril Arrow(p+)
		case 5620: return 22; // Adamant Arrow(p+)
		case 5621: return 24; // Rune Arrow(p+)
		case 5622: return 19; // Bronze Arrow(p++)
		case 5623: return 18; // Iron Arrow(p++)
		case 5624: return 20; // Steel Arrow(p++)
		case 5625: return 21; // Mithril Arrow(p++)
		case 5626: return 22; // Adamant Arrow(p++)
		case 5627: return 24; // Rune Arrow(p++)
		//case 9706: // Training Arrows
		case 11212: return 1116; // Dragon Arrow
		case 11217: return 26; // Dragon Fire Arrows
		case 11222: return 26; // Dragon Fire Arrows
		case 11227: return 1116; // Dragon Arrow(p)
		case 11228: return 1116; // Dragon Arrow(p+)
		case 11229: return 1116; // Dragon Arrow(p++)
		default: return -1;
		} // end of switch
	}

	private int DarkBowDrawBack(final int ID) {
		switch(ID) {
		case 78: return 1110; // Ice Arrow
		case 882: return 1104; // Bronze Arrow
		case 884: return 1105; // Iron Arrow
		case 886: return 1106; // Steel Arrow
		case 888: return 1107; // Mithril Arrow
		case 890: return 1108; // Adamant Arrow
		case 892: return 1109; // Rune Arrow
		case 598:
		case 942: // Bronze Fire Arrow
		case 2532:
		case 2533: // Iron Fire Arrow
		case 2534:
		case 2535: // Steel Fire Arrow
		case 2536:
		case 2537: // Mithril Fire Arrow
		case 2538:
		case 2539: // Adamant Fire Arrow
		case 2540:
		case 2541: return 1113; // Rune Fire Arrow
		case 4160: return 1112; // Broad Arrow
		case 11217:
		case 11222: return 1114; // Dragon Fire Arrow
		case 11212: return 1111; // Dragon Arrow
		default: return -1;
		} // end of switch
	}


	private int AxeDrawBack(final int ID) {
		switch(ID) {
		case 800: return 43; // Bronze Thrownaxe
		case 801: return 42; // Iron Thrownaxe
		case 802: return 44; // Steel Thrownaxe
		case 803: return 45; // Mithril Thrownaxe
		case 804: return 46; // Adamant Thrownaxe
		case 805: return 48; // Rune Thrownaxe
		default: return -1;
		} // end of switch
	}



	private int KnifeDrawBack(final int ID) {
		switch(ID) {
		case 863: return 220; // Iron Knife
		case 864: return 219; // Bronze Knife
		case 865: return 221; // Steel Knife
		case 866: return 223; // Mithril Knife
		case 867: return 224; // Adamant Knife
		case 868: return 225; // Rune Knife
		case 869: return 222; // Black Knife
		case 870: return 219; // Bronze Knife(p)
		case 871: return 220; // Iron Knife(p)
		case 872: return 221; // Steel Knife(p)
		case 873: return 223; // Mithril Knife(p)
		case 874: return 222; // Black Knife(p)
		case 875: return 224; // Adamant Knife(p)
		case 876: return 225; // Rune Knife(p)
		case 5654: return 219; // Bronze Knife(p+)
		case 5655: return 220; // Iron Knife(p+)
		case 5656: return 221; // Steel Knife(p+)
		case 5657: return 223; // Mithril Knife(p+)
		case 5658: return 222; // Black Knife(p+)
		case 5659: return 224; // Adamant Knife(p+)
		case 5660: return 225; // Rune Knife(p+)
		case 5661: return 219; // Bronze Knife(p++)
		case 5662: return 220; // Iron Knife(p++)
		case 5663: return 221; // Steel Knife(p++)
		case 5664: return 223; // Mithril Knife(p++)
		case 5665: return 222; // Black Knife(p++)
		case 5666: return 224; // Adamant Knife(p++)
		case 5667: return 225; // Rune Knife(p++)
		default: return -1;
		} // end of switch
	}


	private int DartDrawBack(final int ID) {
		switch(ID) {
		case 806: return 232; // Bronze Dart
		case 807: return 233; // Iron Dart
		case 808: return 234; // Steel Dart
		case 809: return 235; // Mithril Dart
		case 810: return 236; // Adamant Dart
		case 811: return 237; // Rune Dart
		case 812: return 232; // Bronze Dart(p)
		case 813: return 233; // Iron Dart(p)
		case 814: return 234; // Steel Dart(p)
		case 815: return 235; // Mithril Dart(p)
		case 816: return 236; // Adamant Dart(p)
		case 817: return 237; // Rune Dart(p)
		case 818: return 234; // Poisioned Dart(p)
		case 3093: return 273; // Black Dart
		case 3094: return 273; // Black Dart(p)
		case 5628: return 232; // Bronze Dart(p+)
		case 5629: return 233; // Iron Dart(p+)
		case 5630: return 234; // Steel Dart(p+)
		case 5631: return 273; // Black Dart(p+)
		case 5632: return 235; // Mithril Dart(p+)
		case 5633: return 236; // Adamant Dart(p+)
		case 5634: return 237; // Rune Dart(p+)
		case 5635: return 232; // Bronze Dart(p++)
		case 5636: return 233; // Iron Dart(p++)
		case 5637: return 234; // Steel Dart(p++)
		case 5638: return 273; // Black Dart(p++)
		case 5639: return 235; // Mithril Dart(p++)
		case 5640: return 236; // Adamant Dart(p++)
		case 5641: return 237; // Rune Dart(p++)
		case 11230: return 1123; // Dragon Dart
		case 11231: return 1123; // Dragon Dart(p)
		case 11233: return 1123; // Dragon Dart(p+)
		case 11234: return 1123; // Dragon Dart(p++)
		default: return -1;
		} // end of switch
	}

	private int JavelinDrawBack(final int ID) {
		switch(ID) {
		case 825: return 206; // Bronze Javelin
		case 826: return 207; // Iron Javelin
		case 827: return 208; // Steel Javelin
		case 828: return 209; // Mithril Javelin
		case 829: return 210; // Adamant Javelin
		case 830: return 211; // Rune Javelin
		case 831: return 206; // Bronze Javelin(p)
		case 832: return 207; // Iron Javelin(p)
		case 833: return 208; // Steel Javelin(p)
		case 834: return 209; // Mithri Javelin(p)
		case 835: return 210; // Adamant Javelin(p)
		case 836: return 211; // Rune Javelin(p)
		case 5642: return 206; // Bronze Javelin(p+)
		case 5643: return 207; // Iron Javelin(p+)
		case 5644: return 208; // Steel Javelin(p+)
		case 5645: return 209; // Mithril Javelin(p+)
		case 5646: return 210; // Adamant Javelin(p+)
		case 5647: return 211; // Rune Javelin(p+)
		case 5648: return 206; // Bronze Javelin(p++)
		case 5649: return 207; // Iron Javelin(p++)
		case 5650: return 208; // Steel Javelin(p++)
		case 5651: return 209; // Mithril Javelin(p++)
		case 5652: return 210; // Adamant Javelin(p++)
		case 5653: return 211; // Rune Javelin(p++)
		default: return -1;
		} // end of switch
	}
	public int getRangeDelay() {
		Player p2 = World.getInstance().getPlayerList().get(enemyIndex);
		if (p == null || p2 == null)
			return 1500;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 1)
			return 755;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 2)
			return 755;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 3)
			return 1000;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 4)
			return 1250;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 5)
			return 1250;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 6)
			return 1250;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 7)
			return 1250;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 8)
			return 1250;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 9)
			return 1245;
		if (Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(), p2.getLocation().getX(), p2.getLocation().getY()) == 10)
			return 1245;
		return 1;
	}
	public void attackNpc() {
		if (p == null || p.isDead()) {
			attacking = false;
			return;
		}
		if(combatDelay > 0) {
			return;
		}
		final NPC opp = World.getInstance().getNpcList().get(enemyId);
		if (opp == null || opp.isDead() || opp.getHp() <= 0) {
			attacking = false;
			return;
		}
		p.turnTemporarilyTo(opp);
		opp.getCombat().setCombatDelay(1);
		opp.getCombat().setEnemy(p.getIndex());
		opp.getCombat().setAttacking(true);
		final int distance = Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(),opp.getLocation().getX(), opp.getLocation().getY());
              if (distance <= 1) {
			if(useSpec) {
				Player player = p;
				if (player.getEquipment().get(3) == null) {
					useSpec = false;
					return;
				}
				int id = player.getEquipment().get(3).getId();
				int req = getRequiredLevel(id);
				int meleeDamage =+ p.NPCMaxHitMelee();
				int meleeDamage2 = p.NPCMaxHitMelee();
				if(specialAmount >= req) {
					specialAmount -= req;
					refreshSpecial();
				} else {
					player.getActionSender().sendMessage("You do not have enough special amount left.");
					player.setAttacking(false);
					player.getActionSender().sendConfig(301, 0);
					refreshSpecial();
					return;
				}
				NPC p2 = opp;
				switch (id) {
				case 4151: //whip
					p2.graphics(2108, 0);
					p.animate(1658, 0);
					p2.hit(meleeDamage);
					break;
				case 15259:
					p2.hit(meleeDamage);
					p.animate(12031);
					p.graphics(2144);
					break;
				case 14484:
					p.graphics(1950, 0);
					p.animate(10961, 0);
					p2.animate(403);
					int dclaw1 = meleeDamage/2;
					int dclaw2 = meleeDamage/3;
					int dclaw3 = meleeDamage/4;
					if (p.Defence()) {										
						p2.hit(meleeDamage);
					} else {
						p2.hit(Misc.random(40));
					}
					if (p.Defence()) {										
						p2.hit(dclaw1);
					} else {
						p2.hit(Misc.random(10));
					}
					if (p.Defence()) {										
						p2.hit(dclaw2);
					} else {
						p2.hit(Misc.random(dclaw3));
					}
					if (p.Defence()) {										
						p2.hit(dclaw3);
					} else {
						p2.hit(Misc.random(dclaw2));
					}										
					break;
				case 5698:
					p.graphics(252, (100 << 16));
					p.animate(1062, 0);
					p2.hit(meleeDamage);
					p2.hit(meleeDamage2);
					break;
				case 11730:
					p.graphics(1224, 0);
					p2.graphics(1194, 0);
					p.animate(7072, 0);
					p2.hit(meleeDamage);
					p2.hit(meleeDamage2);
					break;
				case 11694:
					p.graphics(1222, 0);
					p.animate(7074, 0);
					p2.hit(Misc.random((int) (p.NPCMaxHitMelee() * 1.25)));
					break;
				case 11696:
					p.graphics(1223, 0);
					p.animate(7073, 0);
					p2.hit(Misc.random((int) (p.NPCMaxHitMelee()* 1.10)));
					break;
				case 11698:
					p.graphics(1220, 0);
					p.animate(7071, 0);
					p2.hit(meleeDamage);
					break;
				case 11700:
					p.graphics(1221, 0);
					p.animate(7070, 0);
					p2.hit(meleeDamage);
					break;
				case 1305:
					p.graphics(248, 0);
					p.animate(1058, 0);
					p2.hit(Misc.random((int) (p.NPCMaxHitMelee() * 1.20)));
					break;
				case 15241:
                                p2.animate(4177, 0);
                                p.animate(12174, 0);
				p.graphics(2138, 0);
				p2.hit(Misc.random(50));
				p2.hit(Misc.random(40));
				break;
				case 4587:
					p.graphics(347, 0);
					p.animate(2081, 0);
					p2.hit(meleeDamage);
					break;
				case 3204:
					p.graphics(282, 0);
					p2.graphics(254, 0);
					p.animate(1665, 0);
					p2.hit(meleeDamage);
					p2.hit(meleeDamage2);
					break;
				case 1434:
					p.graphics(251, 0);
					p.animate(1060, 0);
					p2.hit(Misc.random((int) (p.NPCMaxHitMelee()* 1.25)));
					break;
				case 7158:
					p.graphics(559, 0);
					p.animate(3157, 0);
					p2.hit(meleeDamage);
					break;
				} 
				player.getActionSender().sendConfig(301, 0);
				refreshSpecial();
				combatDelay = getAttackDelay();
				useSpec = false;
				return;
			}
}
		if(usingRange()) {
			handleRange(p, opp);
			return;
		}
		if (!usingRange() && distance <= 1 && combatDelay == 0) {
			if (p.getEquipment().get(3) != null) {
				p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()));
			} else {
				p.animate(451);
			}
			combatDelay = getAttackDelay();
			World.getInstance().registerEvent(new Event(getDamageDelay()) {
				@Override
				public void execute() {
					final NPC p2 = World.getInstance().getNpcList().get(enemyId);
					p2.animate(p2.getDefenceAnimation());
					int damage = p.NPCMaxHitMelee();;
					p2.hit(damage);
					this.stop();
				}
			});
		}
	}
	private void handleRange(final Player p, final NPC opp) {
		p.getWalkingQueue().reset();
		//final int // = Misc.getDistance(p.getLocation().getX(), p.getLocation().getY(),opp.getLocation().getX(), opp.getLocation().getY());
		if (p.getEquipment().get(3).getDefinition().getId() == 11235) {
			p.animate(426, 0);
			combatDelay = getAttackDelay();
			p.graphics(DarkBowDrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
			int damage = p.NPCMaxHitRange();
			int damage2 = p.NPCMaxHitRange();
			opp.hit(damage);
			opp.hit(damage2);
			return;
		}
		if (usingBow(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(DrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingDarts(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(DartDrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingKnifes(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(KnifeDrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingAxes(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(AxeDrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingJavelins(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
			p.graphics(JavelinDrawBack(p.getEquipment().get(3).getDefinition().getId()), (100 << 16));
		}
		if (usingCrossBow(p)) {
			p.animate(getCombatAnim(p.getEquipment().get(3).getDefinition().getId()), 0);
			combatDelay = getAttackDelay();
		}
		if (usingCrystalBow(p)) {
			p.animate(426, 0);
			p.graphics(250, (100 << 16));
			combatDelay = getAttackDelay();
		}
		World.getInstance().registerEvent(new Event(getRangeDelay()) {
			@Override
			public void execute() {
				opp.animate(opp.getDefenceAnimation());
				int damage = p.NPCMaxHitRange();
				opp.hit(damage);
				this.stop();
			}
		});
	}
	private final static int[] rangeBows = {841, 843, 845, 847, 849, 851, 853, 855, 857, 859, 861, 10284};

	private final static int[] CrossBows = {767, 837, 10156, 11165, 11167, 13081, 8880, 9174, 9176, 9177, 9179, 9181, 9183, 9185, 4675, 13867};
	private final static int[] CrystalBows = {4212, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223};
	private final static int[] Knifes = {863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 5654, 5655, 5656, 5657, 5658, 5659, 5660, 5661, 5662, 5663, 5664, 5665, 5666, 5667};
	private final static int[] Darts = {806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 3093, 3094, 5628, 5629, 5630, 5631, 5632, 5633, 5634, 5635, 5636, 5637, 5638, 5639, 5640, 5641, 11230, 11231, 11233, 11234};
	private final static int[] Axes = {800, 801, 802, 803, 804, 805};
	private final static int[] Javelins = {825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 5642, 5643, 5644, 5645, 5646, 5647, 5648, 5649, 5650, 5651, 5652, 5653};
}
